package com.rp.security.extend;

import java.util.Calendar;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.WebAttributes;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.TextEscapeUtils;

import com.rp.common.utils.RpUtil;
import com.rp.system.dao.UserDao;
import com.rp.system.po.User;
import com.rp.system.service.LoginLogService;

public class MyUsernamePasswordAuthenticationFilter extends
		UsernamePasswordAuthenticationFilter {
	
	public static final String USERNAME = "j_username";
    public static final String PASSWORD = "j_password";
    //此密钥是使用MD5加密字符串：huangjian7758258而来
    public static final String SECRET_KEY = "324014DA368E35A3937A4063FB8863AC";
    
    public static final long MAX_LOGINCOUNT = 5;			//最大登录尝试次数
    public static final long WAIT_MINUTE = 5*60*1000;		//等待时间，默认5分钟，单位为毫秒

	private UserDao userDao;
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
	private LoginLogService loginLogService;
	public void setLoginLogService(LoginLogService loginLogService) {
		this.loginLogService = loginLogService;
	}
	
	private JdbcTemplate jdbcTemplate;
	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
	
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request,
			HttpServletResponse response) throws AuthenticationException {
		
		if (!request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("认证方法不支持：" + request.getMethod());
        }
		
		//获取用户输入的用户名、密码和密钥
		String username = obtainUsername(request);
        String password = obtainPassword(request);
        String secretKey = request.getParameter("secretKey");
        
        if(secretKey == null || secretKey.equals("") || !secretKey.equals(SECRET_KEY)){
        	throw new AuthenticationServiceException("您没有提交密钥，无法进行正常的用户身份验证");
        }
        
        //查询数据库中是否存在此用户名的用户
		User user = userDao.getUserByUsername(username);
		
		if(user != null){
			
			Integer errorLoginCount = user.getErrorLoginCount();
			
			if(errorLoginCount >= MAX_LOGINCOUNT){
				long dbErrorLoginInitMinute = Long.parseLong(user.getErrorLoginInitTimestamp());
				long nowTimestamp = RpUtil.getCurrentDatetimeToTimestamp();
				//System.out.println(nowMinute);
				//System.out.println(dbErrorLoginInitMinute+5);
				if(nowTimestamp > dbErrorLoginInitMinute+WAIT_MINUTE){
					System.out.println("已经等待超过5分钟，可以继续进行登录验证");
				}else{
					HttpSession session = request.getSession(false); 
					if (session != null || this.getAllowSessionCreation()) { 
		                request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, TextEscapeUtils.escapeEntities(username)); 
		            }
					throw new AuthenticationServiceException("尝试登录的次数超过"+MAX_LOGINCOUNT+"次，请等待5分钟之后再做尝试！");
				}
			}
			
			//如果数据库中不存在此用户，或者用户输入的密码与数据库中查询出来的用户的密码不相同
			if(!user.getPassword().equals(RpUtil.md5Encrypt(password))){
				
				errorLoginCount = errorLoginCount + 1;
				jdbcTemplate.update("update RP_SYSTEM_USERS set errorLoginCount = "+errorLoginCount+" where id = ?", 
						user.getId());
				if(errorLoginCount >= MAX_LOGINCOUNT){
					jdbcTemplate.update("update RP_SYSTEM_USERS set errorLoginInitTimestamp = '"+String.valueOf(RpUtil.getCurrentDatetimeToTimestamp())+"' where id = ?", 
							user.getId());
				}
				
				HttpSession session = request.getSession(false); 
	            if (session != null || this.getAllowSessionCreation()) { 
	                request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, TextEscapeUtils.escapeEntities(username)); 
	            }
				throw new AuthenticationServiceException("用户名或者密码错误！");
			}
			
		}else{
			HttpSession session = request.getSession(false);
            if (session != null || this.getAllowSessionCreation()) { 
                request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, TextEscapeUtils.escapeEntities(username)); 
            }
			throw new AuthenticationServiceException("用户名或者密码错误！");
		}
		
		jdbcTemplate.update("update RP_SYSTEM_USERS set errorLoginCount = 0 where id = '"+user.getId()+"'");
		jdbcTemplate.update("update RP_SYSTEM_USERS set errorLoginInitTimestamp = '0' where id = '"+user.getId()+"'");
		
		//登录成功，保存登录日志
		loginLogService.addLoginLog(
				request.getRemoteAddr(), 
				user.getUsername(),
				user.getRealname());
		
		//UsernamePasswordAuthenticationToken实现 Authentication  
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
		
        //允许子类设置详细属性  
        setDetails(request, authRequest);
        
		return this.getAuthenticationManager().authenticate(authRequest);
	}
	
	@Override  
    protected String obtainUsername(HttpServletRequest request) {  
        Object obj = request.getParameter(USERNAME);  
        return null == obj ? "" : obj.toString();  
    }  
  
    @Override  
    protected String obtainPassword(HttpServletRequest request) {   
        Object obj = request.getParameter(PASSWORD);  
        return null == obj ? "" : obj.toString();  
    }
    
    /**
     * 获取当前分钟
     * @return
     */
    protected Integer getNowMinute(){
    	Calendar calendar = Calendar.getInstance();
		Integer nowMinute = calendar.get(Calendar.MINUTE);
		return nowMinute;
    }
	
}
